package com.systemsjr.jrappointment.utils;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.springframework.binding.value.support.RefreshableValueHolder;
import org.springframework.richclient.selection.binding.ListSelectionDialogBinder;
import org.springframework.richclient.selection.binding.support.LabelProvider;
import org.springframework.rules.closure.Closure;

import com.systemsjr.jrappointment.appointment.vo.AppointmentVO;
import com.systemsjr.jrappointment.customer.vo.CustomerVO;
import com.systemsjr.jrappointment.service.vo.ServiceVO;
import com.systemsjr.jrappointment.setting.vo.SystemSettingVO;
import com.systemsjr.jrappointment.user.vo.UserDetailsVO;

public class UIUtils {

	private static RefreshableValueHolder userValueHolder;

	public static RefreshableValueHolder getUserValueHolder() {
		
		return getValueHolder(userValueHolder, ServiceUtils.getUserService().loadAll());
	}

	private static Map<String, Object> userContext;

	public static Map<String, Object> getUserContext() {
		if (userContext == null) {
			userContext = composeContext(getUserValueHolder(), new String[] { "username", "name" }, "users.title");
			
			userContext.put(ListSelectionDialogBinder.LABEL_PROVIDER_KEY,
					new LabelProvider() {

						@Override
						public String getLabel(Object item) {
							UserDetailsVO user = (UserDetailsVO) item;
							return user == null ? "" : user.getUsername() + " "
									+ user.getName();
						}
					});
		}
		return userContext;
	}

	private static RefreshableValueHolder appointmentValueHolder;

	public static RefreshableValueHolder getAppointmentValueHolder() {
		
		return getValueHolder(appointmentValueHolder, ServiceUtils.getAppointmentService().loadAll());
	}

	private static Map<String, Object> appointmentContext;

	public static Map<String, Object> getAppointmentContext() {
		if (appointmentContext == null) {
			appointmentContext = composeContext(getAppointmentValueHolder(), 
					new String[] { "customer.phoneNumber", "customer.name" }, "appointments.title");
			appointmentContext.put(
					ListSelectionDialogBinder.LABEL_PROVIDER_KEY,
					new LabelProvider() {

						@Override
						public String getLabel(Object item) {
							AppointmentVO appointment = (AppointmentVO) item;
							return appointment == null ? "" : appointment
									.getCustomer().getPhoneNumber()
									+ " "
									+ appointment.getCustomer().getName()
									+ " "
									+ appointment.getStartTime();
						}
					});
		}
		return appointmentContext;
	}

	private static RefreshableValueHolder customerValueHolder;

	public static RefreshableValueHolder getCustomerValueHolder() {
		return getValueHolder(customerValueHolder, ServiceUtils.getCustomerService().loadAll());
	}

	private static Map<String, Object> customerContext;

	public static Map<String, Object> getCustomerContext() {
		if (customerContext == null) {
			customerContext = composeContext(getCustomerValueHolder(), new String[] { "phoneNumber", "name" }, "customers.title");
			customerContext.put(ListSelectionDialogBinder.LABEL_PROVIDER_KEY,
					new LabelProvider() {

						@Override
						public String getLabel(Object item) {
							CustomerVO customer = (CustomerVO) item;
							return customer == null ? "" : customer
									.getPhoneNumber()
									+ " "
									+ customer.getName();
						}
					});
		}
		return customerContext;
	}

	private static RefreshableValueHolder serviceValueHolder;

	public static RefreshableValueHolder getServiceValueHolder() {

		return getValueHolder(serviceValueHolder, ServiceUtils.getServiceService().loadAll());
	}

	private static Map<String, Object> serviceContext;

	public static Map<String, Object> getServiceContext() {
		if (serviceContext == null) {
			serviceContext = composeContext(getServiceValueHolder(), new String[] { "code", "serviceName" }, "services.title");
			serviceContext.put(ListSelectionDialogBinder.LABEL_PROVIDER_KEY,
					new LabelProvider() {

						@Override
						public String getLabel(Object item) {
							ServiceVO service = (ServiceVO) item;
							return service == null ? "" : service.getCode()
									+ " " + service.getServiceName();
						}
					});

		}
		return serviceContext;
	}

	private static RefreshableValueHolder invoiceValueHolder;

	public static RefreshableValueHolder getInvoiceValueHolder() {
		
		return getValueHolder(invoiceValueHolder, ServiceUtils.getInvoiceService().loadAll());
	}

	private static Map<String, Object> invoiceContext;

	public static Map<String, Object> getInvoiceContext() {
		if (invoiceContext == null) {
			invoiceContext = composeContext(getInvoiceValueHolder(),
					new String[] { "code", "serviceName" }, "invoices.title");

			invoiceContext.put(ListSelectionDialogBinder.LABEL_PROVIDER_KEY,
					new LabelProvider() {

						@Override
						public String getLabel(Object item) {
							ServiceVO service = (ServiceVO) item;
							return service == null ? "" : service.getCode()
									+ " " + service.getServiceName();
						}
					});
		}
		return invoiceContext;
	}
	
	private static RefreshableValueHolder settingValueHolder;

	public static RefreshableValueHolder getSettingValueHolder() {
		
		return getValueHolder(settingValueHolder, ServiceUtils.getSettingService().loadAll());
	}

	private static Map<String, Object> settingContext;

	public static Map<String, Object> getSettingContext() {
		if (settingContext == null) {
			settingContext = composeContext(getInvoiceValueHolder(),
					new String[] { "registrationNumber", "companyName" }, "settings.title");

			settingContext.put(ListSelectionDialogBinder.LABEL_PROVIDER_KEY,
					new LabelProvider() {

						@Override
						public String getLabel(Object item) {
							SystemSettingVO setting = (SystemSettingVO) item;
							return setting == null ? "" : setting.getRegistrationNumber()
									+ " " + setting.getCompanyName();
						}
					});
		}
		return settingContext;
	}

	private static Map<String, Object> composeContext(
			RefreshableValueHolder valueHolder, String[] filters, String title) {
		Map<String, Object> context = new HashMap<String, Object>();
		context.put(ListSelectionDialogBinder.SELECTABLE_ITEMS_HOLDER_KEY,
				valueHolder);
		context.put(ListSelectionDialogBinder.LABEL_PROVIDER_KEY,
				new LabelProvider() {

					@Override
					public String getLabel(Object item) {
						ServiceVO service = (ServiceVO) item;
						return service == null ? "" : service.getCode() + " "
								+ service.getServiceName();
					}
				});

		context.put(ListSelectionDialogBinder.FILTERED_KEY, Boolean.TRUE);
		context.put(ListSelectionDialogBinder.FILTER_PROPERTIES_KEY, filters);
		context.put(ListSelectionDialogBinder.TITLE_KEY_KEY, title);

		return context;
	}
	
	private static RefreshableValueHolder getValueHolder(RefreshableValueHolder valueHolder, final Collection data) {
		if (valueHolder == null) {
			valueHolder = new RefreshableValueHolder(new Closure() {
				@Override
				public Object call(Object object) {
					return data;
				}

			}, false, false);
		}

		return valueHolder;
	}
	
	/**
	 * Crreates a list of values between min and max based on the step value
	 * 
	 * @param min
	 * @param max
	 * @param step
	 * @return
	 */
	public static List<Integer> getSeries(int min, int max, int step){
		LinkedList<Integer> list = new LinkedList<Integer>();
		
		for(int i = min; i < max; i+=step){
			
			list.add(i);
			
		}
		
		return list;
	}

}
